package drds.server.datasource;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import drds.server.handler.Handler;
import drds.server.route.RouteNode;

public class GroupDataSourceNode {
	protected static final Logger LOGGER = LoggerFactory.getLogger(GroupDataSourceNode.class);

	protected final String hostName;
	protected final String schemaName;
	protected final GroupDataSource groupDataSource;

	public GroupDataSourceNode(String hostName, String schemaName, GroupDataSource groupDataSource) {
		this.hostName = hostName;
		this.schemaName = schemaName;
		this.groupDataSource = groupDataSource;
	}

	public String getHostName() {
		return hostName;
	}

	public GroupDataSource getGroupDataSource() {
		return groupDataSource;
	}

	public String getSchemaName() {
		return schemaName;
	}

	/**
	 * get connection from the same datasource
	 */
	public void getConnectionFromSameSource(String schema, boolean autocommit, IConnectionHolder connectionHolder, Handler handler, Object attachment) throws Exception {

		DataSource dataSource = this.groupDataSource.findDataSource(connectionHolder);
		if (dataSource == null) {
			throw new RuntimeException("can't find exits connection,maybe fininshed " + connectionHolder);
		} else {
			dataSource.getConnection(schema, autocommit, handler, attachment);
		}

	}

	private void check(String schema) {
		if (schema != null && !schema.equals(this.schemaName)) {
			throw new RuntimeException("invalid param ,connection request db is :" + schema + " and datanode db is " + this.schemaName);
		}
		if (!groupDataSource.isInitSuccess()) {
			groupDataSource.init(groupDataSource.currentActivedIndex);
		}
	}

	public void getConnection(String schema, boolean autoCommit, RouteNode node, Handler handler, Object attachment) throws Exception {
		check(schema);
		if (!groupDataSource.isInitSuccess()) {
			throw new IllegalArgumentException("Invalid DataSource:" + groupDataSource.getCurrentActivedIndex());
		} else {
			/**
			 * master/slave标记
			 */
			if (node.masterTrue$SlaveFalse() != null) {
				/** 强制走 master */
				if (node.masterTrue$SlaveFalse()) {
					DataSource writeDataSource = groupDataSource.getWriteDataSource();
					// 记录写节点写负载值
					writeDataSource.addReadCount();
					writeDataSource.getConnection(schema, autoCommit, handler, attachment);
					node.setWriteTrue$ReadFalse(true);

				} else {
					/** 强制走 slave */
					if (node.hasBlanceFlag()) {
						/** 目前好像只支持一个注解 */
						groupDataSource.getConnectionWithBanlanceStrategy(schema, autoCommit, handler, attachment, this.schemaName);
					} else {
						/**
						 * <pre>
						 * 没有 balance 注解,则默认readHost中随机获取一个 connection,如果获取失败则直接读取writeHost
						 * </pre>
						 */
						if (!groupDataSource.getDataSource(schema, autoCommit, handler, attachment, this.schemaName)) {
							DataSource writeDataSource = groupDataSource.getWriteDataSource();
							// 记录写节点写负载值
							writeDataSource.addWriteCount();
							writeDataSource.getConnection(schema, autoCommit, handler, attachment);
							node.setMasterTrue$SlaveFalse(false);
							node.setWriteTrue$ReadFalse(false);
						}
					}

				}
			} else {
				/**
				 * 没有master/slave标记,按照原来的处理方式.优先从读库上面读取,再从写库上面读取
				 */
				if (node.canRunnOnReadDataBase(autoCommit)) {
					groupDataSource.getDataSourceWithBanlanceStrategy(schema, autoCommit, handler, attachment, this.schemaName);
				} else {
					DataSource writeDataSource = groupDataSource.getWriteDataSource();
					// 记录写节点写负载值
					writeDataSource.addWriteCount();
					writeDataSource.getConnection(schema, autoCommit, handler, attachment);
				}
			}

		}
	}
}